package com.example.demo.study.lambda;

import java.util.Optional;

/**
 *     Optional 不是接口而是一个类，这是个用来防止NullPointerException异常的辅助类型
 *     Optional 被定义为一个简单的容器，其值可能是null或者不是null。
 *     在Java8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null，而在Java 8中，不推荐你返回null而是返回Optional。
 *     这是一个可以为null的容器对象。
 *     如果值存在则isPresent()方法会返回true，调用get()方法会返回该对象。
 */
public class LambdaOptional {
    public static void main(String[] args) {

        /*of方法 为非null的值创建一个Optional*/
        //of方法通过工厂方法创建Optional类。
        //需要注意的是，创建对象时传入的参数不能为null。
        //如果传入参数为null，则抛出NullPointerException 。
        Optional<String> opt1 = Optional.of("hello");

        /*ofNullable方法 为指定的值创建一个Optional，如果指定的值为null，则返回一个空的Optional。*/
        //ofNullable与of方法相似，唯一的区别是可以接受参数为null的情况
        Optional<String> opt2 = Optional.ofNullable(null);

        if (opt1.isPresent()){
            System.out.println(opt1.get());
        }

        if(opt2.isPresent()){
            System.out.println(opt2.get());
        }

        /*ifPresent方法 如果Optional实例有值则为其调用consumer，否则不做处理*/
        //consumer接口中的方法只有参数没有返回值
        opt1.ifPresent(str->System.out.println(str));
        opt2.ifPresent(str->System.out.println(str));//这个不执行 因为op2里面的值是null


        /*orElse方法 如果有值则将其返回，否则返回指定的其它值。*/
        System.out.println(opt1.orElse("如果op1中的值为null则返回这句话,否则返回这个值"));
        System.out.println(opt2.orElse("如果op2中的值为null则返回这句话,否则返回这个值"));


        /*orElseGet方法 orElseGet与orElse方法类似，区别在于得到的默认值。orElse方法将传入的字符串作为默认值，orElseGet方法可以接受Supplier接口的实现用来生成默认值。*/
        //Supplier接口中的方法没有参数但是有返回值
        System.out.println(opt1.orElseGet(()->"自己定义的返回值"));
        System.out.println(opt2.orElseGet(()->"自己定义的返回值"));

        /*orElseThrow方法 如果有值则将其返回，否则抛出supplier接口创建的异常。*/
        //在orElseThrow中我们可以传入一个lambda表达式或方法，如果值不存在来抛出异常。
        //orElseThrow方法的声明如下 所有只能返回一个Throwable类型对象
        //public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
        try {
            System.out.println(opt1.orElseThrow(Exception::new));;
            //System.out.println(op2.orElseThrow(Exception::new));;这个会抛出异常
        } catch (Exception e) {
            e.printStackTrace();
        }

        /*map方法 如果有值，则对其执行调用mapper函数得到返回值。*/
        //返回值并且依然Optional包裹起来,其泛型和你返回值的类型一致
        //public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
        Optional<Integer> map1 = opt1.map(str->1);
        System.out.println(map1.get());
        Optional<Double> map2 = opt2.map(str->1.2);
        System.out.println(map2.orElse(0.0));

        /*flatMap方法 如果有值，为其执行mapper函数返回Optional类型返回值，否则返回空Optional。*/
        //flatMap与map方法类似，区别在于flatMap中的mapper返回值必须是Optional。调用结束时，flatMap不会对结果用Optional封装。
        //需要我们自己把返回值封装为Optional
        //public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
        System.out.println(opt1.flatMap(str->Optional.of(str+"_briup")).get());
        //op1.flatMap(str->"");编译出错



    }
}
